"""
数据集访问权限工具模块
提供获取用户有权限访问的数据集的公共方法
"""

from typing import List, Dict, Any, Optional
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import and_, select, or_
from datetime import datetime
from loguru import logger

from app.models.db import DataSet, UserRole, RoleDatasetAccess, Role
from app.utils.auth import get_user_role_codes


async def get_user_accessible_datasets(
    user_id: str,
    session: AsyncSession,
    session_dataset_ids: Optional[List[str]] = None,
    search: Optional[str] = None,
    dataset_type: Optional[int] = None,
    include_summary: bool = False
) -> List[Dict[str, Any]]:
    """
    获取用户有权限访问的数据集列表
    
    Args:
        user_id: 用户ID
        session: 数据库会话
        session_dataset_ids: 会话关联的数据集ID列表，如果提供则优先使用
        search: 搜索关键词，支持模糊匹配名称、描述、原始名称
        dataset_type: 数据集类型筛选 (0=全部, 1=本地, 2=非本地)
        include_summary: 是否包含数据集摘要信息
        
    Returns:
        用户有权限访问的数据集列表
        
    权限逻辑:
        1. 如果提供了session_dataset_ids，优先返回这些数据集
        2. 否则返回用户有权限访问的所有数据集，包括：
           - 用户创建的数据集
           - 用户通过角色授权访问的数据集
           - 管理员可以访问所有数据集
    """
    try:
        available_datasets = []
        
        # 情况1: 如果指定了会话关联的数据集，优先使用
        if session_dataset_ids:
            for dataset_id in session_dataset_ids:
                dataset_query = select(DataSet).where(DataSet.id == dataset_id)
                dataset_result = await session.execute(dataset_query)
                dataset = dataset_result.scalar_one_or_none()
                
                if dataset:
                    dataset_info = _format_dataset_info(dataset, include_summary)
                    available_datasets.append(dataset_info)
            
            return available_datasets
        
        # 情况2: 获取用户有权限访问的所有数据集
        user_role_codes = await get_user_role_codes(user_id, session)
        
        # 构建基础查询
        dataset_query = select(DataSet)
        
        # 如果用户不是管理员，需要添加权限过滤
        if "admin" not in user_role_codes:
            # 获取用户的角色ID
            role_query = select(UserRole.role_id).where(UserRole.user_id == user_id)
            role_result = await session.execute(role_query)
            role_ids = [row[0] for row in role_result.all()]
            
            # 构建权限过滤条件
            permission_filter = or_(
                DataSet.user_id == user_id,  # 用户创建的数据集
                DataSet.id.in_(
                    select(RoleDatasetAccess.dataset_id)
                    .where(
                        RoleDatasetAccess.role_id.in_(role_ids),
                        or_(
                            RoleDatasetAccess.expires_at == None,
                            RoleDatasetAccess.expires_at > datetime.now()
                        )
                    )
                )  # 用户通过角色有权限访问的数据集
            )
            dataset_query = dataset_query.where(permission_filter)
        
        # 添加数据集类型筛选
        if dataset_type is not None:
            if dataset_type == 1:  # 本地数据集
                dataset_query = dataset_query.filter(
                    DataSet.data_source_id == '00000000-0000-0000-0000-000000000000'
                )
            elif dataset_type == 2:  # 非本地数据集
                dataset_query = dataset_query.filter(
                    DataSet.data_source_id != '00000000-0000-0000-0000-000000000000'
                )
        
        # 添加搜索条件
        if search and search.strip():
            search_pattern = f"%{search.strip()}%"
            dataset_query = dataset_query.filter(
                or_(
                    DataSet.name.ilike(search_pattern),
                    DataSet.description.ilike(search_pattern),
                    DataSet.original_name.ilike(search_pattern)
                )
            )
        
        # 执行查询
        datasets_result = await session.execute(dataset_query)
        datasets = datasets_result.scalars().all()
        
        # 格式化数据集信息
        for dataset in datasets:
            dataset_info = _format_dataset_info(dataset, include_summary)
            available_datasets.append(dataset_info)
        
        return available_datasets
        
    except Exception as e:
        logger.error(f"获取用户可访问数据集失败: {str(e)}")
        return []


async def check_user_dataset_access(
    user_id: str,
    dataset_id: str,
    session: AsyncSession
) -> Dict[str, Any]:
    """
    检查用户是否有权限访问指定数据集
    
    Args:
        user_id: 用户ID
        dataset_id: 数据集ID
        session: 数据库会话
        
    Returns:
        权限检查结果，包含has_access、can_export等信息
    """
    try:
        # 获取用户角色
        user_role_codes = await get_user_role_codes(user_id, session)
        
        # 管理员有权限访问所有数据集
        if "admin" in user_role_codes:
            return {
                "has_access": True,
                "can_export": True,
                "access_type": "admin"
            }
        
        # 检查是否是用户创建的数据集
        dataset_query = select(DataSet).where(
            DataSet.id == dataset_id,
            DataSet.user_id == user_id
        )
        result = await session.execute(dataset_query)
        dataset = result.scalar_one_or_none()
        
        if dataset:
            return {
                "has_access": True,
                "can_export": True,
                "access_type": "owner"
            }
        
        # 检查通过角色授权的访问权限
        role_query = select(UserRole.role_id).where(UserRole.user_id == user_id)
        role_result = await session.execute(role_query)
        role_ids = [row[0] for row in role_result.all()]
        
        if not role_ids:
            return {
                "has_access": False,
                "access_type": "none"
            }
        
        # 查询角色对该数据集的访问权限
        access_query = select(RoleDatasetAccess).where(
            RoleDatasetAccess.role_id.in_(role_ids),
            RoleDatasetAccess.dataset_id == dataset_id,
            or_(
                RoleDatasetAccess.expires_at == None,
                RoleDatasetAccess.expires_at > datetime.now()
            )
        )
        access_result = await session.execute(access_query)
        accesses = access_result.scalars().all()
        
        if not accesses:
            return {
                "has_access": False,
                "access_type": "none"
            }
        
        # 如果有任何一个角色允许导出，则用户可以导出
        can_export = any(access.can_export for access in accesses)
        
        return {
            "has_access": True,
            "can_export": can_export,
            "access_type": "role",
            "role_count": len(accesses)
        }
        
    except Exception as e:
        logger.error(f"检查数据集访问权限失败: {str(e)}")
        return {
            "has_access": False,
            "access_type": "error",
            "error": str(e)
        }


def _format_dataset_info(dataset: DataSet, include_summary: bool = True) -> Dict[str, Any]:
    """
    格式化数据集信息
    
    Args:
        dataset: 数据集对象
        include_summary: 是否包含摘要信息
        
    Returns:
        格式化后的数据集信息字典
    """
    dataset_info = {
        "id": dataset.id,
        "name": dataset.name,
        "dataset_summary": dataset.dataset_summary
    }
    return dataset_info


async def get_user_accessible_knowledge_bases(
    user_id: str,
    session: AsyncSession
) -> List[int]:
    """
    获取用户有权限访问的知识库ID列表
    
    Args:
        user_id: 用户ID
        session: 数据库会话
        
    Returns:
        List[int]: 用户有权限访问的知识库ID列表
    """
    try:
        from app.models.db import KnowledgeBase, UserRole, Role
        
     
        
        
        accessible_kb_ids = []
        
        # 1. 获取所有公开的知识库
        public_query = select(KnowledgeBase.id).where(
            and_(
                KnowledgeBase.status == 1,
                KnowledgeBase.access_level == "public"
            )
        )
        result = await session.execute(public_query)
        accessible_kb_ids.extend([row[0] for row in result.all()])
        
        # 获取用户角色
        user_role_codes = await get_user_role_codes(user_id, session)
        # 2. 获取用户有角色权限的知识库
        if user_role_codes:
            # 获取用户的角色ID列表
            role_names = user_role_codes.split(",")
            role_query = select(Role.id).where(Role.name.in_(role_names))
            role_result = await session.execute(role_query)
            role_ids = [row[0] for row in role_result.all()]
            
            if role_ids:
                # 查询基于角色的知识库
                role_based_query = select(KnowledgeBase.id).where(
                    and_(
                        KnowledgeBase.status == 1,
                        KnowledgeBase.access_level == "role_based",
                        KnowledgeBase.allowed_roles.is_not(None)
                    )
                )
                result = await session.execute(role_based_query)
                role_based_kbs = result.scalars().all()
                
                # 检查每个角色控制的知识库
                for kb_id in role_based_kbs:
                    kb_query = select(KnowledgeBase).where(KnowledgeBase.id == kb_id)
                    kb_result = await session.execute(kb_query)
                    kb = kb_result.scalar_one_or_none()
                    
                    if kb and kb.allowed_roles:
                        # 检查用户角色是否在允许列表中
                        allowed_role_ids = kb.allowed_roles if isinstance(kb.allowed_roles, list) else []
                        if any(str(role_id) in map(str, allowed_role_ids) for role_id in role_ids):
                            accessible_kb_ids.append(kb_id)
        
        # 去重并返回
        return list(set(accessible_kb_ids))
        
    except Exception as e:
        logger.error(f"获取用户可访问知识库失败: {str(e)}")
        return [] 